package com.xiashitech.apiservice.job.base;

import cn.hutool.extra.spring.SpringUtil;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.HashMap;
import java.util.Map;

/**
 * 从JobDetail和Trigger中获取JobData，判断其属性值是否为字符串，若为字符串则判断spring上线问中是否存在同名的bean，若存在则将改变注入该jobbean的属性中，属性名为：JobData的属性名+"Bean"。
 */
public abstract class XSQuartzJobBean extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        try {
            Map jobDataMap = new HashMap();
            jobDataMap.putAll(context.getScheduler().getContext());
            jobDataMap.putAll(context.getMergedJobDataMap());
            Map beanAttributeMap = new HashMap();
            jobDataMap.forEach((attrName,beanName) -> {
                if(beanName instanceof String) {
                    try {
                        Object attributeBean = SpringUtil.getApplicationContext().getBean((String)beanName);
                        if(attributeBean != null) {
                            beanAttributeMap.put(attrName+"Bean",attributeBean);
                        }
                    } catch (NoSuchBeanDefinitionException e) {
                    }
                }
            });
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            MutablePropertyValues pvs = new MutablePropertyValues();
            pvs.addPropertyValues(beanAttributeMap);
            bw.setPropertyValues(pvs, true);
        } catch (SchedulerException ex) {
            throw new JobExecutionException(ex);
        }
        xsExecuteInternal(context);
    }
    protected abstract void xsExecuteInternal(JobExecutionContext context) throws JobExecutionException;
}
